﻿using System;
using System.Data;
using Newtonsoft.Json;

namespace Syncronization.REST
{
    public class DataSetConverter : JsonConverter
    {
        #region Fields

        private const string TablesProperty = "Tables";

        #endregion

        #region public

        /// <summary>
        /// Determines whether this instance can convert the specified value type.
        /// </summary>
        /// <param name="valueType">Type of the value.</param>
        /// <returns>
        ///     <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
        /// </returns>
        public override bool CanConvert(Type valueType)
        {
            return typeof (DataSet).IsAssignableFrom(valueType);
        }

        /// <summary>
        /// Reads the JSON representation of the object.
        /// </summary>
        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <returns>The object value.</returns>
        public override object ReadJson(JsonReader reader, Type objectType)
        {
            var dataSet = new DataSet();

            reader.Read();
            if (reader.TokenType == JsonToken.PropertyName && (string) reader.Value == TablesProperty)
            {
                var converter = new DataTableConverter();
                reader.Read();
                if (reader.TokenType == JsonToken.StartArray)
                {
                    reader.Read();
                    while (reader.TokenType != JsonToken.EndArray)
                    {
                        var dataTable = (DataTable) converter.ReadJson(reader, typeof (DataTable));
                        if (dataTable != null)
                            dataSet.Tables.Add(dataTable);

                        //Puts us at start of the next object or end of array
                        if (reader.TokenType == JsonToken.EndObject)
                            reader.Read();
                    }
                }
            }

            return dataSet;
        }

        /// <summary>
        /// Writes the JSON representation of the object.
        /// </summary>
        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="value">The value.</param>
        public override void WriteJson(JsonWriter writer, object value)
        {
            var dataSet = value as DataSet;

            var converter = new DataTableConverter();

            writer.WriteStartObject();

            writer.WritePropertyName(TablesProperty);
            writer.WriteStartArray();

            foreach (DataTable table in dataSet.Tables)
            {
                converter.WriteJson(writer, table);
            }
            writer.WriteEndArray();
            writer.WriteEndObject();
        }

        #endregion
    }
}